// ref和reactive区别
// reactive内部采用proxy

import { track, trigger } from "./effect.js"
import { reactive } from "./reactive.js"

// ref内部使用的是definedProperty
// 对象的话，则会去调用reactive
export function ref(value) {
    return createRef(value)
}
export function shallowRef(value) {
    return createRef(value, true)
}
const covery = (value) => value instanceof Object ? reactive(value): value
class RefImpl {
    __value
    rawValue
    shallow
    __v_isRef = true
    constructor(rawValue, shallow) {
        // 浅的，直接返回，属性访问器 bable=》 definedProperty
        // 如果是对象，则使用reactive =》 proxy
        this.__value = shallow ? rawValue : covery(rawValue)
        this.rawValue = rawValue
        this.shallow = shallow
    }
    // 属性访问器 bable=》 definedProperty
    get value() {
        track(this, 'get', 'value')
        return this.__value
    }
    set value (newValue) {
        if (newValue !== this.rawValue) {
            // 有变化，新值则作为老值
            this.rawValue = newValue
            // 之前的constructor初始化也要更新
            this.__value = this.shallow ? newValue : covery(newValue)
            trigger(this, 'set', 'value', newValue)
        }
       
    }
}
function createRef(rawValue, shallow = false) {
    return new RefImpl(rawValue, shallow)
}


class ObjectRefImpl {
    __value
    key
    __v_isRef = true
    constructor(target, key) {
        this.__value = target
        this.key = key
    }
    // 属性访问器 
    // bable=》 definedProperty
    // toRef(target, key) target本身是响应式的
    // 相等于将target改成get set访问器的形式
    get value() {
        return this.__value[this.key]
    }
    set value(newValue) {
        this.__value[this.key] = newValue
    }
}
export function toRef(target, key) {
    return new ObjectRefImpl(target, key)
}

export function toRefs(target) {
    const ret = Array.isArray(target) ? Array(target.length) : {}
    for(let key in target) {
        ret[key] = toRef(target, key)
    }
    return ret
}

// toRaw 将代理的数据转化为原始数据
// markRaw 不可被proxy代理